package com.auxgroup.smarthome.service;

import com.auxgroup.smarthome.BeanUtils;
import com.auxgroup.smarthome.entity.RoleEntity;
import com.auxgroup.smarthome.entity.SysMessageEntity;
import com.auxgroup.smarthome.entity.SysMessageSendEntity;
import com.auxgroup.smarthome.entity.UserEntity;
import com.auxgroup.smarthome.filter.PermissionSecurityUserService;
import com.auxgroup.smarthome.repo.RoleRepo;
import com.auxgroup.smarthome.repo.SysMessageEntityRepo;
import com.auxgroup.smarthome.repo.SysMessageSendEntityRepo;
import com.auxgroup.smarthome.repo.UserRepo;
import com.auxgroup.smarthome.syscode.Syscode;
import com.auxgroup.smarthome.vo.SysMessageIdVo;
import com.auxgroup.smarthome.vo.SysMessageTagVo;
import com.auxgroup.smarthome.vo.SysMessageVo;
import com.auxgroup.smarthome.web.ApiResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Created by fju on 2017/8/7.
 * 站内信
 */
@Service
public class SysMessageService {

    @Autowired
    private SysMessageEntityRepo sysMessageEntityRepo;
    @Autowired
    private SysMessageSendEntityRepo sysMessageSendEntityRepo;
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private UserRepo userRepo;
    @Autowired
    private RoleRepo roleRepo;
    @Autowired
    private PermissionSecurityUserService permissionSecurityUserService;

    /**
     * 查询站内信收件列表
     * @param keyword
     * @param page
     * @param size
     * @return
     */
    public ApiResponse<Page<SysMessageEntity>> getSysMessageList(final String keyword, Integer page, Integer size){
        if(page == null || size == null){
            return ApiResponse.prompt(Syscode.DTO_PARAMS_ERROR);
        }
        String createUser = permissionSecurityUserService.getSubjectFromAccessToken();
        Sort sort = new Sort(Sort.Direction.DESC, "sendTime");
        Pageable pageable = new PageRequest(page, size, sort);
        Specification<SysMessageEntity> spec = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if(keyword != null){
                predicates.add(criteriaBuilder.like(root.get("title"), "%"+ keyword +"%"));
            }
            predicates.add(criteriaBuilder.equal(root.get("trash"), false));
            predicates.add(criteriaBuilder.equal(root.get("createdBy"), createUser));
            criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
            return criteriaQuery.getRestriction();
        };
        return ApiResponse.ok(sysMessageEntityRepo.findAll(spec,pageable));
    }

    /**
     * 新增站内信
     * @param title
     * @param content
     * @param roleId 收件人角色ID
     * @return
     */
    @Transactional
    public ApiResponse<SysMessageIdVo> addSysMessage(String title, String content, String roleId){
        //获取当前登录者信息
        String createUser = permissionSecurityUserService.getSubjectFromAccessToken();
        UserEntity userEntity = userRepo.findOne(createUser);
        if(userEntity == null) {
            return ApiResponse.prompt(Syscode.ACCOUNT_NOT_EXISTS);
        }

        RoleEntity role = roleRepo.findByIdAndDisableFalse(roleId);
        String roleName = role.getRoleName();
        //检查角色是否存在
        if(role == null){
            return ApiResponse.prompt(Syscode.ROLE_NOT_EXISTS);
        }
        //保存消息
        SysMessageEntity sysMessageEntity = new SysMessageEntity(title, content, roleId, roleName, createUser);
        sysMessageEntityRepo.save(sysMessageEntity);

        // 查询该角色下的所有用户Id ，用户和消息产生逻辑关联（发送消息）
        ApiResponse sendInMailResult = sendInMailMessage(roleId, sysMessageEntity.getSysMessageId(), userEntity.getId(), userEntity.getRealName());
        if(!sendInMailResult.isNotErrorCode()) {
            return sendInMailResult;
        }
        return ApiResponse.ok(new SysMessageIdVo(sysMessageEntity.getSysMessageId()));
    }

    /**
     * 通过角色发送信件
     * @param roleId 角色id
     * @param inMailId 信件id
     * @return
     */
    public ApiResponse sendInMailMessage(String roleId, String inMailId, String senderId, String senderName){
        //查询该角色下的所有用户Id ，用户和消息产生逻辑关联（发送消息）
        List<String> userIds = userService.getUserIds(roleId);
        if(userIds.size() < 1) {
            return ApiResponse.prompt(Syscode.SYS_MSG_ROLE_NOT_USERS);
        }
        List<SysMessageSendEntity> preSendMsgs = new ArrayList<>();
        for (String userId : userIds) {
            SysMessageSendEntity msg = new SysMessageSendEntity(inMailId, userId, senderId, senderName);
            preSendMsgs.add(msg);
        }
        sysMessageSendEntityRepo.save(preSendMsgs);
        return ApiResponse.ok();
    }

    /**
     * 获取单条站内信
     * @param sysMessageId
     * @return
     */
    public ApiResponse<SysMessageVo> getSysMessage(String sysMessageId){
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();
        SysMessageEntity sysMessageEntity = sysMessageEntityRepo.findOne(sysMessageId);
        if(sysMessageEntity == null){
           return ApiResponse.prompt(Syscode.SYS_MSG_NOT_FOUND);
        }
        SysMessageSendEntity sysMessageSendEntity = sysMessageSendEntityRepo.findByUserIdAndSysMessageId(userId,sysMessageEntity.getSysMessageId());
        if(sysMessageSendEntity == null){
           return ApiResponse.prompt(Syscode.SYS_MSG_NOT_RECEIVED);
        }
        SysMessageVo sysMessageVo  = BeanUtils.copyAttrs(new SysMessageVo(),sysMessageEntity);
        sysMessageVo.setProgress(sysMessageSendEntity.getProgress());
        return ApiResponse.ok(sysMessageVo);
    }

    /**
     * 站内信接收列表
     * 根据UserId和Keyword来查询接收列表
     * @param keyword
     * @param pageable
     * @return
     */
    public ApiResponse<Page<SysMessageVo>> getReceivedSysMessageList(String keyword, Pageable pageable){
        StringBuffer querySql = new StringBuffer("select sys_message.*, sys_message_send.progress, sys_message_send.sender_id, sys_message_send.sender_name from sys_message ");
        querySql.append(" left join sys_message_send on sys_message.sys_message_id = sys_message_send.sys_message_id ");
        querySql.append(" where sys_message_send.progress != 2  and user_id = ? ");
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();
        Sort sort = new Sort(Sort.Direction.DESC, "sendTime");
        Pageable pageRequest = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(), sort);

        List<Object> params = new ArrayList<>();
        params.add(userId);
        if(StringUtils.isNotEmpty(keyword)){
            querySql.append(" and  sys_message.title like ? ");
            params.add("%"+keyword+"%");
        }
        querySql.append(" order by sys_message.send_time desc ");
        Page<SysMessageVo> pageResult = sysMessageEntityRepo.findBySql(querySql.toString(), params, pageRequest, SysMessageVo.class);
        return ApiResponse.ok(pageResult);
    }

    /**
     * 获取收件列表
     * @param id
     * @param progress
     * @return
     */
    public ApiResponse<List<SysMessageVo>> getSysMessageListByProgress(String id, Integer progress){
        StringBuffer querySql = new StringBuffer("select sys_message.*, sys_message_send.progress, sys_message_send.sender_id, sys_message_send.sender_name  from sys_message left join sys_message_send on sys_message.sys_message_id = sys_message_send.sys_message_id where user_id = ? ");
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();

        List<Object> params = new ArrayList<>();
        params.add(userId);
        if(null == progress){
            querySql.append(" and  sys_message_send.progress != 2 ");
        } else {
            querySql.append(" and  sys_message_send.progress = ? ");
            params.add(progress);
        }
        if(StringUtils.isNotEmpty(id)) {
            querySql.append(" and  sys_message.sys_message_id = ? ");
            params.add(id);
        }
        querySql.append(" order by sys_message.send_time desc ");
        List<SysMessageVo> result = sysMessageEntityRepo.findBySql(querySql.toString(), params, SysMessageVo.class);
        return ApiResponse.ok(result);
    }

    /**
     * 清空当前用户所有站内信收件列表
     * @return
     */
    @Transactional
    public ApiResponse clearAllReceiveInMailOfCurrUser(){
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();
        int row = sysMessageSendEntityRepo.updateProgressToDel(userId);
        if(row>0){
            return ApiResponse.prompt(Syscode.SC_OK);
        }
        return ApiResponse.prompt(Syscode.FAIL);
    }

    /**
     * 清空当前用户所有站内信发件列表
     * @return
     */
    @Transactional
    public ApiResponse clearAllSendInMailOfCurrUser(){
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();
        int row = sysMessageEntityRepo.clearSysMessageByUserId(userId);
        if(row>0){
            return ApiResponse.prompt(Syscode.SC_OK);
        }
        return ApiResponse.prompt(Syscode.FAIL);
    }

    /**
     * 删除站内信发件人
     * @param sysMessageIds 消息id,多个用英文,隔开
     * @return
     */
    @Transactional
    public ApiResponse deleteSendInMail(String sysMessageIds){
        List<String> sysMesIdsList = Arrays.asList(sysMessageIds.split(","));
        int row = sysMessageEntityRepo.deleteSysMessageByUserId(sysMesIdsList);
        if(row>0){
            return ApiResponse.prompt(Syscode.SC_OK);
        }
        return ApiResponse.prompt(Syscode.FAIL);
    }

    /**
     * 标记站内信息
     * 根据UserId 和 messageSendId 来标记为 progress
     * @param sysMessageId 消息主键，有多个用,分隔
     * @param progress 进度 0.未阅 1.已阅 2.已删除
     * @return
     */
    @Transactional
    public ApiResponse<SysMessageTagVo> tagSysMessage(String sysMessageId, Integer progress){
        //校验
        if(sysMessageId == null || progress == null){
            return ApiResponse.prompt(Syscode.DTO_PARAMS_ERROR);
        }
        String userId = permissionSecurityUserService.getSubjectFromAccessToken();
        sysMessageId = sysMessageId.trim();
        String[] messageSendIds = sysMessageId.split(",");
        Collection<String> ids = new ArrayList<>();
        for (String id: messageSendIds) {
            ids.add(id);
        }
        if (ids.size() == 0){
            return ApiResponse.prompt(Syscode.FAIL);
        }
        int row = sysMessageSendEntityRepo.updateProgress(userId,progress,ids);
        return ApiResponse.ok(new SysMessageTagVo(row));
    }
}
